package com.yhy.tradesystem.techdata;

import java.security.acl.LastOwnerException;
import java.util.ArrayList;

import com.yhy.tradesystem.PositionMoneyController;
import com.yhy.tradesystem.TradeDataPak;
import com.yhy.tradesystem.TradeManager;
import com.yhy.tradesystem.TradeSystemFilter;
import com.yhy.tradesystem.TradeDataPak.StockData;
import com.yhy.tradesystem.buysellsignal.BaseBuySellSignalFilter;
import com.yhy.tradesystem.datasource.BaseDataSource;
import com.yhy.tradesystem.util.DataPakLogger;
import com.yhy.tradesystem.util.Log;

public class TechDataBestParameterFinder implements TradeSystemFilter{

	String testFilterClassName;
	String testSignalClassName;
	String testParameterName;
	ArrayList<TradeDataPak.StockData> bufferData;
	int testTickLength=0;
	TradeDataPak pak;
	PositionMoneyController controller;
	private float[] defaultFilterParaValue;
	private String[] defaultFilterParaKey;
	private String testOutputFilterValue;
	
	private String[] defaultSignalStringParaValue;
	private String[] defaultSignalStringParaKey;
	
	/**
	 * 测试某个技术指标在某个买卖信号下的最优参数
	 * @param
	 * 
	 * testFilterClassName 技术指标的类名称<br>
	 * defaultFilterParaKey 除了要测试的参数，其他需要设置默认数值的参数名<br>
	 * defaultFilterParaValue 除了要测试的参数，其他需要设置默认数值的参数数值<br>
	 * testParameterName 测试的参数名称<br>
	 * testOutputFilterValue 测试参数影响的技术指标名称，采用 名称/指标名 的格式<br>
	 * testSignalClassName 测试买卖信号类名称
	 * defaultSignalStringParaKey 买卖信号需要配置的参数名称
	 * defaultSignalStringParaValue 买卖信号需要配置的参数数值
	 * testTickLength 回测寻找最优参数所用的数据的长度，在长度没缓冲够以前需要一直输入数据
	 * */
	public TechDataBestParameterFinder(String testFilterClassName, String defaultFilterParaKey[],float defaultFilterParaValue[] ,
			String testParameterName,String testOutputFilterValue,
			String testSignalClassName, String defaultSignalStringParaKey[],String defaultSignalStringParaValue[] ,
			int testTickLength) {
		super();
		this.testFilterClassName = testFilterClassName;
		this.testParameterName = testParameterName;
		this.testSignalClassName = testSignalClassName;
		this.testTickLength = testTickLength;
		this.defaultFilterParaKey = defaultFilterParaKey;
		this.defaultFilterParaValue = defaultFilterParaValue;
		this.defaultSignalStringParaKey = defaultSignalStringParaKey;
		this.defaultSignalStringParaValue = defaultSignalStringParaValue;
		this.testOutputFilterValue = testOutputFilterValue;
		bufferData = new ArrayList<TradeDataPak.StockData>();
	}

	@Override
	public void connectOutput(TradeSystemFilter filter) {
		
	}
	
	/***
	 * 在当前已经缓冲的数据内进行回测寻找最优参数
	 * @return
	 * 最优参数与最优参数对应的技术指标
	 **/
	public float[] getCurrentBestParameters(float rangeStart, float rangeEnd,
			float step) {
		float[] ret={0.0f,0.0f};
		if(bufferData.size()<testTickLength){
			return ret;
		}
		float best = -1f;
		float bestpar = rangeStart;
		float besttechvalue = 0.0f;
		
		for (float par = rangeStart; par < rangeEnd; par += step) {
			try {
				Class tClass = Class.forName(testFilterClassName);
				Class sClass = Class.forName(testSignalClassName);

				BaseTechDataFilter tfilter = (BaseTechDataFilter) tClass
						.newInstance();
				if(defaultFilterParaKey!=null){
					for (int i = 0; i < defaultFilterParaKey.length; i++) {
						tfilter.setParameters(defaultFilterParaKey[i], defaultFilterParaValue[i]);
					}
				}
				tfilter.setParameters(testParameterName, par);
				
				BaseBuySellSignalFilter sfilter = (BaseBuySellSignalFilter) sClass
						.newInstance();
				if(defaultSignalStringParaKey!=null){
					for (int i = 0; i < defaultSignalStringParaKey.length; i++) {
						sfilter.setStringParameters(defaultSignalStringParaKey[i], defaultSignalStringParaValue[i]);
					}
				}

				controller = new PositionMoneyController();

				tfilter.connectOutput(sfilter);
				sfilter.connectOutput(controller);
				
//				DataPakLogger logger = new DataPakLogger(MAFilter.DATA_MA+"/"+MAFilter.DATA_MA, "/home/hyyang/temp/stock/log"+par);
//				logger.openLog();
//				sfilter.connectOutput(logger);
				
				float begin = controller.getCurrentMoney();
				float lastTechData = 0.0f;
				for (int i = 0; i < bufferData.size(); i++) {
					TradeDataPak data = new TradeDataPak();
					data.stockData = bufferData.get(i);
					tfilter.inputData(data);
					if(i == bufferData.size()-1){
						lastTechData = data.pickValueFromTradeDataPak(testOutputFilterValue);
					}
				}
				controller.forceCloseAllTrade();
				float end = controller.getCurrentMoney();
//				Log.d(getName(),"%f %f",par,(end-begin));
				if(end-begin > best){
					best = end-begin;
					bestpar = par;
					besttechvalue = lastTechData;
//					besttechvalue = 
				}
//				logger.closeLog();
				
				
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
				return ret;
			} catch (InstantiationException e) {
				e.printStackTrace();
				return ret;
			} catch (IllegalAccessException e) {
				e.printStackTrace();
				return ret;
			}
		}
		Log.d(getName(), "%s,%f,%f,%f", bufferData.get(bufferData.size()-1).date.toGMTString(), bufferData.get(bufferData.size()-1).close,bestpar,besttechvalue);
		ret[0] = bestpar;
		ret[1] = besttechvalue;
		return ret;
	}

	@Override
	public void inputData(TradeDataPak data) {
		this.pak = data;
		
		if(bufferData.size() >testTickLength){
			bufferData.remove(0);
		}
		bufferData.add(data.stockData);
	}

	@Override
	public TradeDataPak outputData() {
		return this.pak;
	}

	@Override
	public String getName() {
		return "技术指标最优测试";
	}

	@Override
	public void resetData() {
		bufferData.clear();
	}


}
